﻿package CutLoad.cookies
{
	import CutLoad.cookies.Fun;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;

	/**
	 * 对socket进行简单的包装，简化了一些事件方法的处理，和发送socket数据，采数队列的形式发送。这样不至于太快，因为有时候flash反应很慢
	 * @author smallerbird mail:smallerbird@gmail.com  site:www.mkigm.com QQ群:49983196
	 * 
	 */	
	public class CSocket
	{
		public var socket:Socket=null;
		private var url:String;
		private var port:int;
		private var connect:Function,getData:Function,fun_close:Function,error:Function,securityError:Function;
		//
		public function CSocket(url:String,port:int):void{
			if(socket!=null) throw new Error("有一个连接存在!");
			socket=new Socket();
			//
			this.url=url;
			this.port=port;
			connect=getData=fun_close=error=securityError=function():void{}
		}
		/**
		 * 设置要处理的事件的函数
		 * 
		 * @param connect 连接上的函数
		 * @param getData 获得数据时的函数 ，注：需要一个参数，用来获得socket来自服务器的自符串
		 * @param close 半闭时的函数
		 * @param error 错误时的函数
		 * 
		 * 生成的模版，请复制下面进行修改<br>
		 * setEventFun(socketConnect,socketGetData,socketClose,socketError);
		 * <br>
		 * private function socketConnect():void{<br>
		 * 	//连接上的函数<br>
		 * }<br>
		 * private function socketGetData(str:String):void{<br>
		 * 	//获得数据时的函数<br>
		 * }<br>
		 * private function socketClose():void{<br>
		 * 	//半闭时的函数<br>
		 * }<br>
		 * private function socketError():void{<br>
		 * 	//错误时的函数<br>
		 * }<br>
		 *  
		 *
		 */		
		public function setEventFun(connect:Function,getData:Function,close123:Function,error:Function,securityError:Function=null):void{
			this.connect=connect
			this.getData=getData
			this.fun_close=close123
			this.error=error
			if(securityError==null){
				this.securityError=error;	
			}else{
				this.securityError=securityError;	
			}
			//
			socket.addEventListener(Event.CONNECT, onConnect);
			socket.addEventListener(ProgressEvent.SOCKET_DATA, onSocketData );
			socket.addEventListener(IOErrorEvent.IO_ERROR, onIOError );
			socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			socket.addEventListener(Event.CLOSE, onclose);
			//
			if(!socket.connected) socket.connect(url,port);
		}	
		/**
		 *关闭socket 
		 * @return 
		 * 
		 */		
		public function close():void{
			connect=getData=fun_close=error=securityError=null;
			if(socket.connected) socket.close();
			if(socket.hasEventListener(Event.CONNECT)) socket.removeEventListener( Event.CONNECT, onConnect );
			if(socket.hasEventListener(ProgressEvent.SOCKET_DATA)) socket.removeEventListener( ProgressEvent.SOCKET_DATA, onSocketData );
			if(socket.hasEventListener(IOErrorEvent.IO_ERROR)) socket.removeEventListener(IOErrorEvent.IO_ERROR, onIOError );
			if(socket.hasEventListener(SecurityErrorEvent.SECURITY_ERROR)) socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
			if(socket.hasEventListener(Event.CLOSE)) socket.removeEventListener(Event.CLOSE, onclose);
			socket=null;
			//
		}
		/**
		 * 发送一行数据，注此函数会自动在数据加一行换行符 
		 * @param str
		 * @return 
		 * 
		 */		
		public function sendData(str:String):Boolean{
			str+="\n";
			socket.writeUTFBytes(str);
			socket.flush();
			return true;
		}
		//
		//在建立网络连接后调度
		private function onConnect(e:Event):void{	
			connect();
		}
		//在套接字接收到数据后调度。
		private function onSocketData(e:ProgressEvent):void{	
			var strResult:String=socket.readUTF();
			getData(strResult);
		}
		//在出现输入/输出错误并导致发送或加载操作失败时调度。
		private function onIOError(e:IOErrorEvent):void{	
			error();
		}
		//若对 Socket.connect() 的调用尝试连接到调用方安全沙箱外部的服务器或端口号低于 1024 的端口，则进行调度。
		private function onSecurityError(e:SecurityErrorEvent):void{
			securityError();
		}
		//在服务器关闭套接字连接时调度。
		private function onclose(e:Event):void{
			fun_close();
		}
		
		
	}
}